#!/usr/bin/env python3
"""
Demo Server - Simplified version to demonstrate core functionality
"""

import asyncio
import json
import time
import uuid
import os
import pickle
import hashlib
import secrets
import configparser
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import websockets
from websockets.server import serve
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
import threading
import logging

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Load configuration
config = configparser.ConfigParser()
config_file = 'config.ini'

def load_config():
    """Load configuration from config.ini"""
    global config
    try:
        if os.path.exists(config_file):
            config.read(config_file, encoding='utf-8')
            logger.info(f"Configuration loaded from {config_file}")
        else:
            logger.warning(f"Configuration file {config_file} not found, using defaults")
            # Create default config if file doesn't exist
            create_default_config()
    except Exception as e:
        logger.error(f"Error loading configuration: {e}")
        create_default_config()

def create_default_config():
    """Create default configuration"""
    global config
    config['proxy'] = {
        'enabled': 'true',
        'host': '127.0.0.1',
        'port': '7890',
        'type': 'http'
    }
    config['binance'] = {
        'ws_base_url': 'wss://nbstream.binance.com/eoptions/ws',
        'connect_timeout': '10',
        'reconnect_interval': '5',
        'max_reconnect_attempts': '3'
    }
    config['server'] = {
        'websocket_port': '8770',
        'http_port': '8769',
        'supported_symbols': 'ETHUSDT,BTCUSDT'
    }
    config['trading'] = {
        'initial_balance': '10000.0',
        'profit_rate_10s': '0.8',
        'profit_rate_5m': '0.8',
        'profit_rate_10m': '0.8',
        'profit_rate_30m': '0.85',
        'profit_rate_1h': '0.85',
        'profit_rate_1d': '0.85'
    }

def get_config_value(section, key, default=None):
    """Get configuration value with fallback to default"""
    try:
        return config.get(section, key)
    except (configparser.NoSectionError, configparser.NoOptionError):
        return default

def get_config_bool(section, key, default=False):
    """Get boolean configuration value"""
    try:
        return config.getboolean(section, key)
    except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
        return default

def get_config_int(section, key, default=0):
    """Get integer configuration value"""
    try:
        return config.getint(section, key)
    except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
        return default

def get_config_float(section, key, default=0.0):
    """Get float configuration value"""
    try:
        return config.getfloat(section, key)
    except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
        return default

# Load configuration on startup
load_config()

# In-memory storage
users: Dict[str, dict] = {}  # username -> user data (includes password_hash)
contracts: Dict[str, dict] = {}
prices: Dict[str, dict] = {}  # symbol -> latest price data
klines: Dict[str, List[dict]] = {}  # symbol -> kline data list
connected_clients: set = set()
sessions: Dict[str, dict] = {}  # token -> session data

# Data persistence
DATA_DIR = "data"
USERS_FILE = os.path.join(DATA_DIR, "users.pkl")
CONTRACTS_FILE = os.path.join(DATA_DIR, "contracts.pkl")
KLINES_FILE = os.path.join(DATA_DIR, "klines.pkl")

def ensure_data_dir():
    """Ensure data directory exists"""
    if not os.path.exists(DATA_DIR):
        os.makedirs(DATA_DIR)

def save_users():
    """Save users data to file"""
    ensure_data_dir()
    try:
        with open(USERS_FILE, 'wb') as f:
            pickle.dump(users, f)
        logger.info(f"Saved {len(users)} users to {USERS_FILE}")
    except Exception as e:
        logger.error(f"Failed to save users: {e}")

def load_users():
    """Load users data from file"""
    global users
    try:
        if os.path.exists(USERS_FILE):
            with open(USERS_FILE, 'rb') as f:
                users = pickle.load(f)
            logger.info(f"Loaded {len(users)} users from {USERS_FILE}")
        else:
            logger.info("No users file found, starting with empty data")
    except Exception as e:
        logger.error(f"Failed to load users: {e}")
        users = {}

def save_contracts():
    """Save contracts data to file"""
    ensure_data_dir()
    try:
        with open(CONTRACTS_FILE, 'wb') as f:
            pickle.dump(contracts, f)
        logger.info(f"Saved {len(contracts)} contracts to {CONTRACTS_FILE}")
    except Exception as e:
        logger.error(f"Failed to save contracts: {e}")

def load_contracts():
    """Load contracts data from file"""
    global contracts
    try:
        if os.path.exists(CONTRACTS_FILE):
            with open(CONTRACTS_FILE, 'rb') as f:
                contracts = pickle.load(f)
            logger.info(f"Loaded {len(contracts)} contracts from {CONTRACTS_FILE}")
        else:
            logger.info("No contracts file found, starting with empty data")
    except Exception as e:
        logger.error(f"Failed to load contracts: {e}")
        contracts = {}

def save_klines():
    """Save klines data to file"""
    ensure_data_dir()
    try:
        with open(KLINES_FILE, 'wb') as f:
            pickle.dump(klines, f)
        logger.info(f"Saved klines data for {len(klines)} symbols to {KLINES_FILE}")
    except Exception as e:
        logger.error(f"Failed to save klines: {e}")

def load_klines():
    """Load klines data from file"""
    global klines
    try:
        if os.path.exists(KLINES_FILE):
            with open(KLINES_FILE, 'rb') as f:
                klines = pickle.load(f)
            logger.info(f"Loaded klines data for {len(klines)} symbols from {KLINES_FILE}")
        else:
            logger.info("No klines file found, starting with empty data")
            # 初始化空的K线数据
            for symbol in SUPPORTED_SYMBOLS:
                klines[symbol] = []
    except Exception as e:
        logger.error(f"Failed to load klines: {e}")
        klines = {}
        for symbol in SUPPORTED_SYMBOLS:
            klines[symbol] = []

# Authentication utilities
def hash_password(password: str) -> str:
    """Hash password using SHA-256"""
    return hashlib.sha256(password.encode()).hexdigest()

def verify_password(password: str, password_hash: str) -> bool:
    """Verify password against hash"""
    return hash_password(password) == password_hash

def generate_session_token() -> str:
    """Generate a secure session token"""
    return secrets.token_urlsafe(32)

def create_session(username: str) -> str:
    """Create a new session for user"""
    token = generate_session_token()
    sessions[token] = {
        'username': username,
        'created_at': datetime.now(),
        'expires_at': datetime.now() + timedelta(hours=24)
    }
    return token

def validate_session(token: str) -> Optional[str]:
    """Validate session token and return username if valid"""
    if token not in sessions:
        return None
    
    session = sessions[token]
    if datetime.now() > session['expires_at']:
        del sessions[token]
        return None
    
    return session['username']

def cleanup_expired_sessions():
    """Remove expired sessions"""
    now = datetime.now()
    expired_tokens = [token for token, session in sessions.items() 
                     if now > session['expires_at']]
    for token in expired_tokens:
        del sessions[token]

# Configuration (loaded from config.ini)
SUPPORTED_SYMBOLS = get_config_value('server', 'supported_symbols', 'ETHUSDT,BTCUSDT').split(',')
INITIAL_BALANCE = get_config_float('trading', 'initial_balance', 10000.0)
PROFIT_RATES = {
    "10s": get_config_float('trading', 'profit_rate_10s', 0.8),
    "5m": get_config_float('trading', 'profit_rate_5m', 0.8),
    "10m": get_config_float('trading', 'profit_rate_10m', 0.8),
    "30m": get_config_float('trading', 'profit_rate_30m', 0.85),
    "1h": get_config_float('trading', 'profit_rate_1h', 0.85),
    "1d": get_config_float('trading', 'profit_rate_1d', 0.85)
}
PERIOD_SECONDS = {
    "10s": 10,      # 测试用
    "5m": 300,      # 测试用
    "10m": 600,
    "30m": 1800,
    "1h": 3600,
    "1d": 86400
}

# WebSocket proxy configuration
PROXY_ENABLED = get_config_bool('proxy', 'enabled', True)
PROXY_HOST = get_config_value('proxy', 'host', '127.0.0.1')
PROXY_PORT = get_config_int('proxy', 'port', 7890)
PROXY_TYPE = get_config_value('proxy', 'type', 'http')

# Binance WebSocket configuration
BINANCE_WS_BASE_URL = get_config_value('binance', 'ws_base_url', 'wss://nbstream.binance.com/eoptions/ws')
CONNECT_TIMEOUT = get_config_int('binance', 'connect_timeout', 10)
RECONNECT_INTERVAL = get_config_int('binance', 'reconnect_interval', 5)
MAX_RECONNECT_ATTEMPTS = get_config_int('binance', 'max_reconnect_attempts', 3)

# Server ports
WEBSOCKET_PORT = get_config_int('server', 'websocket_port', 8770)
HTTP_PORT = get_config_int('server', 'http_port', 8769)

# HTTP Request Handler
class ContractHTTPHandler(BaseHTTPRequestHandler):
    """HTTP handler for contract-related requests"""
    
    def do_GET(self):
        """Handle GET requests"""
        parsed_url = urlparse(self.path)
        path = parsed_url.path
        query_params = parse_qs(parsed_url.query)
        
        if path == "/api/contracts":
            self.handle_get_contracts(query_params)
        elif path == "/api/users":
            self.handle_get_users(query_params)
        elif path == "/api/health":
            self.handle_health_check()
        else:
            self.send_error(404, "Not Found")
    
    def do_POST(self):
        """Handle POST requests"""
        parsed_url = urlparse(self.path)
        path = parsed_url.path
        
        # Get request body
        content_length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(content_length).decode('utf-8')
        
        try:
            data = json.loads(body) if body else {}
        except json.JSONDecodeError:
            self.send_json_response({"error": "Invalid JSON"}, 400)
            return
        
        if path == "/api/auth/register":
            self.handle_register(data)
        elif path == "/api/auth/login":
            self.handle_login(data)
        elif path == "/api/auth/logout":
            self.handle_logout(data)
        elif path == "/api/auth/validate":
            self.handle_validate_session(data)
        elif path == "/api/auth/reset":
            self.handle_reset_account(data)
        else:
            self.send_error(404, "Not Found")
    
    def do_OPTIONS(self):
        """Handle preflight requests"""
        self.send_response(200)
        self.send_cors_headers()
        self.end_headers()
    
    def send_cors_headers(self):
        """Send CORS headers"""
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
    
    def send_json_response(self, data, status_code=200):
        """Send JSON response"""
        self.send_response(status_code)
        self.send_header('Content-Type', 'application/json')
        self.send_cors_headers()
        self.end_headers()
        json_data = json.dumps(data, ensure_ascii=False).encode('utf-8')
        self.wfile.write(json_data)
    
    def handle_get_contracts(self, query_params):
        """Handle GET /api/contracts"""
        try:
            username = query_params.get('user_id', [None])[0]  # 参数名保持user_id但实际是username
            
            if username:
                # Get contracts for specific user (支持新旧数据格式)
                user_contracts = []
                
                # 查找新格式的合约（使用username字段）
                for contract in contracts.values():
                    if contract.get("username") == username:
                        user_contracts.append(contract)
                
                # 查找旧格式的合约（使用user_id字段，需要通过用户数据映射）
                user = users.get(username)
                if user:
                    user_uuid = user.get("id")
                    if user_uuid:
                        for contract in contracts.values():
                            if contract.get("user_id") == user_uuid and not contract.get("username"):
                                user_contracts.append(contract)
                # Sort by creation time (newest first)
                user_contracts.sort(key=lambda x: x.get("created_at", ""), reverse=True)
                self.send_json_response({
                    "success": True,
                    "contracts": user_contracts,
                    "total": len(user_contracts)
                })
            else:
                # Get all contracts
                all_contracts = list(contracts.values())
                all_contracts.sort(key=lambda x: x.get("created_at", ""), reverse=True)
                self.send_json_response({
                    "success": True,
                    "contracts": all_contracts,
                    "total": len(all_contracts)
                })
        except Exception as e:
            logger.error(f"Error handling get_contracts: {e}")
            self.send_json_response({"error": str(e)}, 500)
    
    def handle_get_users(self, query_params):
        """Handle GET /api/users"""
        try:
            username = query_params.get('user_id', [None])[0]  # 参数名保持user_id但实际是username
            
            if username:
                user = users.get(username)
                if user:
                    safe_user = {k: v for k, v in user.items() if k != 'password_hash'}
                    self.send_json_response({"success": True, "user": safe_user})
                else:
                    self.send_json_response({"error": "User not found"}, 404)
            else:
                # Get all users (without sensitive info)
                safe_users = {username: {"id": u["id"], "username": u["username"], "balance": u["balance"]} 
                             for username, u in users.items()}
                self.send_json_response({
                    "success": True,
                    "users": safe_users,
                    "total": len(safe_users)
                })
        except Exception as e:
            logger.error(f"Error handling get_users: {e}")
            self.send_json_response({"error": str(e)}, 500)
    
    def handle_health_check(self):
        """Handle GET /api/health"""
        try:
            self.send_json_response({
                "status": "healthy",
                "websocket_clients": len(connected_clients),
                "total_users": len(users),
                "total_contracts": len(contracts),
                "active_sessions": len(sessions),
                "supported_symbols": SUPPORTED_SYMBOLS,
                "timestamp": datetime.now().isoformat()
            })
        except Exception as e:
            logger.error(f"Error handling health_check: {e}")
            self.send_json_response({"error": str(e)}, 500)
    
    def handle_register(self, data):
        """Handle POST /api/auth/register"""
        try:
            username = data.get('username', '').strip()
            password = data.get('password', '').strip()
            
            if not username or not password:
                self.send_json_response({"error": "用户名和密码不能为空"}, 400)
                return
            
            if len(username) < 2:
                self.send_json_response({"error": "用户名至少需要2个字符"}, 400)
                return
                
            if len(password) < 6:
                self.send_json_response({"error": "密码至少需要6个字符"}, 400)
                return
            
            # Check if user already exists
            if username in users:
                self.send_json_response({"error": "用户名已存在"}, 409)
                return
            
            # Create new user
            password_hash = hash_password(password)
            
            user = {
                "id": username,  # 使用username作为唯一ID
                "username": username,
                "password_hash": password_hash,
                "balance": INITIAL_BALANCE,
                "created_at": datetime.now().isoformat(),
                "contracts": []
            }
            
            users[username] = user
            save_users()
            
            # Create session
            token = create_session(username)
            
            # Return user info (without password hash)
            safe_user = {k: v for k, v in user.items() if k != 'password_hash'}
            
            self.send_json_response({
                "success": True,
                "message": "注册成功",
                "user": safe_user,
                "token": token
            })
            
            logger.info(f"New user registered: {username}")
            
        except Exception as e:
            logger.error(f"Error handling register: {e}")
            self.send_json_response({"error": str(e)}, 500)
    
    def handle_login(self, data):
        """Handle POST /api/auth/login"""
        try:
            username = data.get('username', '').strip()
            password = data.get('password', '').strip()
            
            if not username or not password:
                self.send_json_response({"error": "用户名和密码不能为空"}, 400)
                return
            
            # Check if user exists
            user = users.get(username)
            if not user:
                self.send_json_response({"error": "用户名或密码错误"}, 401)
                return
            
            # Verify password
            if not verify_password(password, user['password_hash']):
                self.send_json_response({"error": "用户名或密码错误"}, 401)
                return
            
            # Create session
            token = create_session(username)
            
            # Return user info (without password hash)
            safe_user = {k: v for k, v in user.items() if k != 'password_hash'}
            
            self.send_json_response({
                "success": True,
                "message": "登录成功",
                "user": safe_user,
                "token": token
            })
            
            logger.info(f"User logged in: {username}")
            
        except Exception as e:
            logger.error(f"Error handling login: {e}")
            self.send_json_response({"error": str(e)}, 500)
    
    def handle_logout(self, data):
        """Handle POST /api/auth/logout"""
        try:
            token = data.get('token', '')
            
            if token and token in sessions:
                username = sessions[token]['username']
                del sessions[token]
                logger.info(f"User logged out: {username}")
                self.send_json_response({"success": True, "message": "退出成功"})
            else:
                self.send_json_response({"error": "无效的会话"}, 401)
                
        except Exception as e:
            logger.error(f"Error handling logout: {e}")
            self.send_json_response({"error": str(e)}, 500)
    
    def handle_validate_session(self, data):
        """Handle POST /api/auth/validate"""
        try:
            token = data.get('token', '')
            
            username = validate_session(token)
            if username:
                user = users.get(username)
                if user:
                    safe_user = {k: v for k, v in user.items() if k != 'password_hash'}
                    self.send_json_response({
                        "success": True,
                        "valid": True,
                        "user": safe_user
                    })
                else:
                    self.send_json_response({"success": True, "valid": False})
            else:
                self.send_json_response({"success": True, "valid": False})
                
        except Exception as e:
            logger.error(f"Error handling validate_session: {e}")
            self.send_json_response({"error": str(e)}, 500)
    
    def handle_reset_account(self, data):
        """Handle POST /api/auth/reset"""
        try:
            # 验证Authorization头
            auth_header = self.headers.get('Authorization', '')
            if not auth_header.startswith('Bearer '):
                self.send_json_response({"error": "未提供有效的授权令牌"}, 401)
                return
            
            token = auth_header[7:]  # Remove 'Bearer ' prefix
            username = validate_session(token)
            
            if not username:
                self.send_json_response({"error": "会话已过期，请重新登录"}, 401)
                return
            
            request_username = data.get('username', '').strip()
            
            # 验证请求的用户名与会话用户名一致
            if request_username != username:
                self.send_json_response({"error": "权限不足"}, 403)
                return
            
            # 检查用户是否存在
            user = users.get(username)
            if not user:
                self.send_json_response({"error": "用户不存在"}, 404)
                return
            
            # 重置用户数据
            user["balance"] = INITIAL_BALANCE
            user["contracts"] = []
            
            # 删除该用户的所有合约记录
            contracts_to_remove = []
            for contract_id, contract in contracts.items():
                contract_username = contract.get("username") or contract.get("user_id")
                if contract_username == username:
                    contracts_to_remove.append(contract_id)
            
            for contract_id in contracts_to_remove:
                del contracts[contract_id]
            
            # 保存数据
            save_users()
            save_contracts()
            
            logger.info(f"User {username} account reset successfully")
            
            self.send_json_response({
                "success": True,
                "message": "账户重置成功",
                "new_balance": INITIAL_BALANCE
            })
            
        except Exception as e:
            logger.error(f"Error handling reset_account: {e}")
            self.send_json_response({"error": str(e)}, 500)
    
    def log_message(self, format, *args):
        """Override to reduce log noise"""
        pass

async def connect_to_binance_websocket(symbol: str):
    """Connect to Binance WebSocket for real price data"""
    url = f"{BINANCE_WS_BASE_URL}/{symbol}@index"
    connection_attempts = 0
    max_attempts = MAX_RECONNECT_ATTEMPTS

    while connection_attempts < max_attempts:
        try:
            logger.info(f"连接到币安WebSocket: {symbol} (尝试 {connection_attempts + 1}/{max_attempts})")
            
            # 准备连接参数
            connect_kwargs = {
                'ping_interval': 300,
                'ping_timeout': 900,
                'timeout': CONNECT_TIMEOUT
            }
            
            # 如果启用代理，添加代理配置
            if PROXY_ENABLED:
                try:
                    import socks
                    import socket
                    
                    logger.info(f"使用代理连接: {PROXY_TYPE}://{PROXY_HOST}:{PROXY_PORT}")
                    
                    # 设置SOCKS代理
                    if PROXY_TYPE.lower() == 'socks4':
                        socks.set_default_proxy(socks.SOCKS4, PROXY_HOST, PROXY_PORT)
                    elif PROXY_TYPE.lower() == 'socks5':
                        socks.set_default_proxy(socks.SOCKS5, PROXY_HOST, PROXY_PORT)
                    else:
                        # HTTP代理通过环境变量设置
                        import os
                        proxy_url = f"http://{PROXY_HOST}:{PROXY_PORT}"
                        os.environ['https_proxy'] = proxy_url
                        os.environ['http_proxy'] = proxy_url
                        logger.info(f"设置HTTP代理环境变量: {proxy_url}")
                    
                    if PROXY_TYPE.lower() in ['socks4', 'socks5']:
                        # 为websockets库应用SOCKS代理
                        socket.socket = socks.socksocket
                        logger.info(f"✅ SOCKS代理已设置: {PROXY_TYPE}://{PROXY_HOST}:{PROXY_PORT}")
                    
                except ImportError:
                    logger.warning("pysocks库未安装，无法使用SOCKS代理。请运行: pip install pysocks")
                    # 降级到HTTP代理（如果适用）
                    if PROXY_TYPE.lower() in ['http', 'https']:
                        import os
                        proxy_url = f"http://{PROXY_HOST}:{PROXY_PORT}"
                        os.environ['https_proxy'] = proxy_url
                        os.environ['http_proxy'] = proxy_url
                        logger.info(f"降级使用HTTP代理: {proxy_url}")
                    else:
                        logger.error("无法设置代理，将尝试直接连接")
                except Exception as e:
                    logger.error(f"代理配置错误: {e}")
                    logger.info("将尝试直接连接")
            else:
                logger.info("代理已禁用，直接连接币安WebSocket")
            
            async with websockets.connect(url, **connect_kwargs) as websocket:
                logger.info(f"✅ {symbol} WebSocket连接成功")
                connection_attempts = 0  # 重置连接尝试次数

                async for message in websocket:
                    try:
                        data = json.loads(message)
                        # 验证数据格式: {"e": "index", "E": timestamp, "s": symbol, "p": price}
                        if data.get("e") == "index" and data.get("s") == symbol:
                            prices[symbol] = data
                            await broadcast_price_update(data)
                            logger.info(f"📈 {symbol} 真实价格: {data['p']} (clients: {len(connected_clients)})")
                    except json.JSONDecodeError as e:
                        logger.error(f"❌ {symbol} 消息解析失败: {e}")
                    except Exception as e:
                        logger.error(f"❌ {symbol} 处理消息错误: {e}")

        except Exception as e:
            connection_attempts += 1
            logger.error(f"❌ {symbol} WebSocket连接错误: {e}")
            if connection_attempts < max_attempts:
                logger.info(f"🔄 {symbol} {RECONNECT_INTERVAL}秒后重连...")
                await asyncio.sleep(RECONNECT_INTERVAL)
            else:
                logger.error(f"❌ {symbol} 连接失败，价格将显示为0")
                # 设置价格为0表示连接失败
                price_data = {
                    "e": "index",
                    "E": int(time.time() * 1000),
                    "s": symbol,
                    "p": "0"
                }
                prices[symbol] = price_data
                await broadcast_price_update(price_data)
                break
        finally:
            # 恢复环境变量
            if PROXY_ENABLED and PROXY_TYPE.lower() in ['http', 'https']:
                try:
                    if 'old_proxy' in locals() and old_proxy:
                        os.environ['https_proxy'] = old_proxy
                    elif 'https_proxy' in os.environ:
                        del os.environ['https_proxy']
                except:
                    pass

async def broadcast_price_update(price_data: dict):
    """Broadcast price update to all connected clients"""
    global connected_clients
    if connected_clients:
        message = json.dumps({
            "type": "price_update",
            "data": price_data
        })
        
        disconnected = set()
        for client in connected_clients.copy():
            try:
                await client.send(message)
            except websockets.exceptions.ConnectionClosed:
                disconnected.add(client)
        
        # Clean up disconnected clients
        connected_clients -= disconnected

async def start_price_feeds():
    """Start real-time price feeds from Binance"""
    tasks = []
    for symbol in SUPPORTED_SYMBOLS:
        task = asyncio.create_task(connect_to_binance_websocket(symbol))
        tasks.append(task)

    # 等待所有WebSocket连接
    await asyncio.gather(*tasks, return_exceptions=True)

async def check_expired_contracts():
    """Check and settle expired contracts"""
    while True:
        current_time = int(time.time() * 1000)
        
        for contract_id, contract in contracts.items():
            if contract["status"] == "active" and contract["expiry_timestamp"] <= current_time:
                await settle_contract(contract_id)
        
        await asyncio.sleep(5)  # Check every 5 seconds

async def settle_contract(contract_id: str):
    """Settle an expired contract"""
    contract = contracts.get(contract_id)
    if not contract or contract["status"] != "active":
        return
    
    symbol = contract["symbol"]
    current_price_data = prices.get(symbol)
    
    if not current_price_data:
        # Mark as unknown
        contract["status"] = "unknown"
        # Refund user
        # 支持新旧数据格式
        username = contract.get("username") or contract.get("user_id")
        user = users[username]
        user["balance"] += contract["bet_amount"]
        logger.warning(f"Contract {contract_id} marked as unknown - no price data")
        return
    
    final_price = float(current_price_data["p"])
    contract["final_price"] = final_price
    
    # Determine if prediction was correct
    price_increased = final_price > contract["anchor_price"]
    prediction_correct = (
        (contract["direction"] == "up" and price_increased) or
        (contract["direction"] == "down" and not price_increased)
    )
    
    # 支持新旧数据格式
    username = contract.get("username") or contract.get("user_id")
    user = users[username]
    
    if prediction_correct:
        # Calculate profit
        profit_rate = PROFIT_RATES[contract["period"]]
        profit = contract["bet_amount"] * profit_rate
        contract["profit"] = profit
        
        # Return bet amount + profit
        user["balance"] += contract["bet_amount"] + profit
        logger.info(f"Contract {contract_id} won: profit {profit} USDT")
    else:
        # Loss - no return (bet amount already deducted)
        contract["profit"] = -contract["bet_amount"]
        logger.info(f"Contract {contract_id} lost: {contract['bet_amount']} USDT")
    
    contract["status"] = "settled"
    contract["settled_at"] = datetime.now().isoformat()
    
    # Save to files
    save_contracts()
    save_users()  # Save updated balance

async def handle_client(websocket, path):
    """Handle WebSocket client connections"""
    connected_clients.add(websocket)
    logger.info(f"Client connected. Total clients: {len(connected_clients)}")
    
    try:
        async for message in websocket:
            try:
                data = json.loads(message)
                response = await handle_message(data)
                await websocket.send(json.dumps(response))
            except Exception as e:
                error_response = {"error": str(e)}
                await websocket.send(json.dumps(error_response))
    except websockets.exceptions.ConnectionClosed:
        pass
    finally:
        connected_clients.discard(websocket)
        logger.info(f"Client disconnected. Total clients: {len(connected_clients)}")

async def handle_message(data: dict) -> dict:
    """Handle incoming WebSocket messages"""
    action = data.get("action")
    
    if action == "create_contract":
        username = data.get("user_id")  # 前端传的是user_id，但实际是username
        symbol = data.get("symbol")
        period = data.get("period")
        direction = data.get("direction")
        bet_amount = data.get("bet_amount")
        
        # Validation
        if not all([username, symbol, period, direction, bet_amount]):
            return {"error": "Missing required fields"}
        
        if symbol not in SUPPORTED_SYMBOLS:
            return {"error": f"Unsupported symbol: {symbol}"}
        
        if period not in PERIOD_SECONDS:
            return {"error": f"Unsupported period: {period}"}
        
        if direction not in ["up", "down"]:
            return {"error": f"Invalid direction: {direction}"}
        
        user = users.get(username)
        if not user:
            return {"error": "User not found"}
        
        if user["balance"] < bet_amount:
            return {"error": "Insufficient balance"}
        
        # Get current price
        current_price_data = prices.get(symbol)
        if not current_price_data:
            return {"error": f"No price data available for {symbol}"}

        anchor_price = float(current_price_data["p"])

        # 检查价格是否为0（连接失败状态）
        if anchor_price == 0:
            return {"error": f"Price service unavailable for {symbol}. Cannot create contract when price is 0."}

        # 使用当前系统时间而不是币安时间戳，避免时间偏差
        anchor_timestamp = int(time.time() * 1000)  # 当前时间的毫秒时间戳
        expiry_timestamp = anchor_timestamp + (PERIOD_SECONDS[period] * 1000)
        
        # Create contract
        contract_id = str(uuid.uuid4())
        contract = {
            "id": contract_id,
            "username": username,  # 使用username而不是user_id
            "symbol": symbol,
            "period": period,
            "direction": direction,
            "bet_amount": bet_amount,
            "anchor_price": anchor_price,
            "anchor_timestamp": anchor_timestamp,
            "expiry_timestamp": expiry_timestamp,
            "status": "active",
            "created_at": datetime.now().isoformat()
        }
        
        contracts[contract_id] = contract
        
        # Deduct balance
        user["balance"] -= bet_amount
        
        # Save to files
        save_contracts()
        save_users()  # Save updated balance
        
        return {"success": True, "contract": contract}
    
    elif action == "get_contracts":
        username = data.get("user_id")
        if username:
            # 支持新旧数据格式
            user_contracts = [c for c in contracts.values() 
                            if c.get("username") == username or c.get("user_id") == username]
            return {"contracts": user_contracts}
        else:
            return {"contracts": list(contracts.values())}
    
    elif action == "get_prices":
        return {"prices": prices}
    
    else:
        return {"error": f"Unknown action: {action}"}

def start_http_server():
    """Start HTTP server in a separate thread"""
    def run_server():
        httpd = HTTPServer(("0.0.0.0", HTTP_PORT), ContractHTTPHandler)
        logger.info(f"🌐 HTTP server started on http://0.0.0.0:{HTTP_PORT}")
        httpd.serve_forever()
    
    thread = threading.Thread(target=run_server, daemon=True)
    thread.start()
    return thread

async def main():
    """Main server function"""
    print("Starting Event Contract Demo Server...")
    print("=" * 50)
    print("⚠️  注意：需要代理才能连接到币安WebSocket")
    print("🌐 代理设置：127.0.0.1:7890")
    print()
    
    # Load existing data
    print("📂 Loading existing data...")
    load_users()
    load_contracts()
    
    # Start HTTP server
    http_thread = start_http_server()

    # Start background tasks
    price_task = asyncio.create_task(start_price_feeds())
    contract_task = asyncio.create_task(check_expired_contracts())
    
    # Start WebSocket server
    server = await serve(handle_client, "0.0.0.0", WEBSOCKET_PORT)
    
    print("✅ Demo server started!")
    print(f"📡 WebSocket server: ws://localhost:{WEBSOCKET_PORT}")
    print(f"🌐 HTTP API server: http://localhost:{HTTP_PORT}")
    print("🎯 Supported symbols:", SUPPORTED_SYMBOLS)
    print("⏰ Supported periods:", list(PERIOD_SECONDS.keys()))
    print(f"🔗 Proxy enabled: {PROXY_ENABLED}")
    if PROXY_ENABLED:
        print(f"🌐 Proxy: {PROXY_TYPE}://{PROXY_HOST}:{PROXY_PORT}")
    print("\n📖 Usage:")
    print(f"WebSocket: ws://localhost:{WEBSOCKET_PORT}")
    print('{"action": "create_user", "username": "test"}')
    print('{"action": "get_prices"}')
    print('{"action": "create_contract", "user_id": "...", "symbol": "ETHUSDT", "period": "10s", "direction": "up", "bet_amount": 100}')
    print("\nHTTP API:")
    print(f"GET http://localhost:{HTTP_PORT}/api/contracts?user_id=<user_id>")
    print(f"GET http://localhost:{HTTP_PORT}/api/users?user_id=<user_id>")
    print(f"GET http://localhost:{HTTP_PORT}/api/health")
    print("\nPress Ctrl+C to stop")
    
    try:
        await server.wait_closed()
    except KeyboardInterrupt:
        print("\n🛑 Shutting down server...")
        print("💾 Saving data...")
        save_users()
        save_contracts()
        price_task.cancel()
        contract_task.cancel()
        server.close()
        await server.wait_closed()

if __name__ == "__main__":
    asyncio.run(main())
